<?php
namespace app\common\repositories\info;
use app\common\repositories\BaseRepository;
use app\common\dao\info\AdTaskDao as dao;
use app\common\repositories\user\UserBalanceRepository;
use app\common\repositories\user\UserRepository;
use basic\services\WechatService;
use think\exception\ValidateException;
use think\facade\Db;

/**
 * @mixin dao
 */
class AdTaskRepository extends BaseRepository
{

    const SERVICE_PRICE = 8;

    public function __construct(dao $dao)
    {
        $this->dao = $dao;
    }


    public function getApiLst($where,$page,$limit)
    {
        $uid = request()->uid();
        $count = $this->dao->search(['status'=>2])->count();
        $list = $this->dao->search(['status'=>2])->page($page,$limit)
            ->orderRaw("field(ad.uid,{$uid}),ad.create_time desc")->field('ad.*')->with([
                'user'=>function($query){
                    $query->field('uid,nickname,avatar,phone');
                }
            ])->select();

        return compact('count','list');
    }


    public function getUserLst($where,$page,$limit)
    {
        $uid = request()->uid();

        // 我领取的
        if($where['type'] == 1){
            /**@var $adTask AdTaskRecordRepository**/
            $adTask = app()->make(AdTaskRecordRepository::class);

            $count = $adTask->getSearch()->alias('ar')->where('ar.uid',$uid)
                ->where(['ar.type'=>1,'ar.is_valid'=>1])->order('ar.create_time desc')->group('ar.task_id')->count();

            $ids =  $adTask->getSearch()->alias('ar')->where('ar.uid',$uid)
                ->where(['ar.type'=>1,'ar.is_valid'=>1])->order('ar.create_time desc')
                ->page($page,$limit)
                ->group('ar.task_id')->column('ar.task_id');

            $list = $this->dao->getSearch()->whereIn('task_id',$ids)->with([
                'user'=>function($query){
                    $query->field('uid,nickname,avatar,phone');
                }])->select()->each(function ($item)use ($uid,$adTask){
                    $item['valid_price'] = $adTask->getSearch()->field('ad.*')->where(['uid'=>$uid,'is_valid'=>1,'task_id'=>$item['task_id']])->sum('price');
            });

            return compact('count','list');
        }


        // 我发布的
        $where['uid'] = $uid;
        $count = $this->dao->search(['status'=>[1,2,3,-1],'uid'=>$uid])->count();
        $list = $this->dao->search(['status'=>[1,2,3,-1],'uid'=>$uid])->field('ad.*')->page($page,$limit)
            ->with([
            'user'=>function($query){
                $query->field('uid,nickname,avatar,phone');
            }])->order("ad.create_time desc")->select();

        return compact('count','list');
    }



    public function getAdminLst($where,$page,$limit)
    {
        $count = $this->dao->search($where)->count();
        $list = $this->dao->search($where)->page($page,$limit)
            ->order("create_time desc")->field('ad.*')->with([
                'user'=>function($query){
                    $query->field('uid,nickname,avatar,phone');
                }
            ])->select();

        return compact('count','list');
    }



    // 首次分享收益
    public function share($id)
    {
        $user = request()->userInfo();
        if(!$user->member){
            throw new ValidateException('非代理无分享获得收益权益');
        }

        $task = $this->dao->get($id);
        if(!$task || !in_array($task->status,[2,3])){
            throw new ValidateException('任务无效');
        }

        if($user->uid == $task->uid){
            throw new ValidateException('本人分享无收益');
        }


        if($task->share_left_count <= 0){
            throw new ValidateException('分享已无收益');
        }


        /**@var $adTask AdTaskRecordRepository**/
        $adTask = app()->make(AdTaskRecordRepository::class);

        // 只有第一次分享收益
        if($adTask->getWhere(['uid'=>request()->uid,'type'=>1,'task_id'=>$id,'is_valid'=>1])){
            throw new ValidateException('第一次分享才有收益');
        }

        // todo 设置发布多少条广告后才可以获取收益  need_to_publish_ad_count
        $needCount = systemConfig('need_to_publish_ad_count') ? : 0;

        $count = $this->dao->getSearch()->where('uid',$user->uid)->whereIn('status',[2,3]);
        if($count < $needCount){
            throw new ValidateException('发布广告次数未达标');
        }

        // todo 一天可以分享多少次广告收益
        $shareCount = systemConfig('day_can_share_count') ? : 0;
        $userShareCount = $adTask->getSearch()->where(['uid'=>request()->uid,'type'=>1,'is_valid'=>1])
        ->where('create_time','>=',date('Y-m-d 00:00:00'))->count();

        if($userShareCount >= $shareCount){
            throw new ValidateException('每日分享收益次数已满');
        }

        Db::transaction(function ()use($user,$adTask,$task){

            $adTask->create([
                'uid'=>$user->uid,
                'type'=>1,
                'is_valid'=>1,
                'price'=>$task->single_price,
                'task_id'=>$task->task_id,
            ]);

            // 增加用户余额
            /**@var $balance UserBalanceRepository**/
            $balance = app()->make(UserBalanceRepository::class);
            $balance->recordBalance($user->uid,1,'share_ad','分享广告收益',$task->single_price);

            // 减少分享次数
            $this->dao->incrNumberField($task->task_id,'share_left_count',-1);


            $newTask = $this->dao->get($task->task_id);
            if($newTask->share_left_count == 0){
                $newTask->save(['status'=>3]);
            }
        });
    }






    public function record($id,$share_uid,$openid)
    {
        // todo 设置观看多少庙后算一次收益  watch_ad_get_money_time

        // 用户是否本人
        /**@var $adTask AdTaskRecordRepository**/
        $adTask = app()->make(AdTaskRecordRepository::class);

        $task = $this->dao->get($id);
        if(!$task || !in_array($task->status,[2,3])){
            throw new ValidateException('任务无效');
        }

        // 发布者分享出去的 无收益
        if($share_uid == $task->uid){
            throw new ValidateException('本人分享无收益');
        }


        if($task->share_left_count <= 0){
            throw new ValidateException('分享已无收益');
        }


        if(!$openid){
            throw new ValidateException('参数有误');
        }


        // 分享者分享出去的  分享者浏览时无收益
        $user = app()->make(UserRepository::class)->userInfoByWechatOpenId($openid);


        if($user && ($user->uid == $share_uid || $user->uid == $task->uid)){
            throw new ValidateException('分享者/发布者浏览时无收益');
        }


        if($adTask->getCount(['openid'=>$openid,'type'=>0,'is_valid'=>1,'uid'=>$share_uid,'task_id'=>$id])){
            throw new ValidateException('当前分享已计算收益');
        }



        $shareUser = app()->make(UserRepository::class)->get($share_uid);
        if(!$shareUser){
            throw new ValidateException('分享者不存在');
        }

        if(!$shareUser->member){
            throw new ValidateException('分享者不是代理');
        }


        // todo 设置发布多少条广告后才可以获取收益  need_to_publish_ad_count
        $needCount = systemConfig('need_to_publish_ad_count') ? : 0;

        $count = $this->dao->getSearch()->where('uid',$share_uid)->whereIn('status',[2,3]);
        if($count < $needCount){
            throw new ValidateException('分享者发布广告次数未达标');
        }

        Db::transaction(function ()use($shareUser,$adTask,$task,$openid){

            $adTask->create([
                'uid'=>$shareUser->uid,
                'type'=>0,
                'is_valid'=>1,
                'price'=>$task->single_price,
                'task_id'=>$task->task_id,
                'openid'=>$openid,
            ]);

            // 增加用户余额
            /**@var $balance UserBalanceRepository**/
            $balance = app()->make(UserBalanceRepository::class);
            $balance->recordBalance($shareUser->uid,1,'share_ad','分享广告用户浏览收益',$task->single_price);

            // 减少分享次数
            $this->dao->incrNumberField($task->task_id,'share_left_count',-1);
        });
    }


    public function create($data)
    {
        $user = request()->userInfo();
        $userCan = (bool)systemConfig('user_can_publish_ad');

        if(!$user->member && !$userCan){
            throw new ValidateException('无权限！请先开通代理');
        }

        /**@var $make AdPackageRepository**/
        $make = app()->make(AdPackageRepository::class);
        $package = $make->get($data['package_id']);
        if(!$package){
            throw new ValidateException('套餐已失效');
        }

        $price = $package->price;

        $singlePrice = bcdiv(bcsub($price,self::SERVICE_PRICE,2),$package->count,2);

        $insertData = [
            'order_sn'=> getOrderSn('AD'),
            'content' => $data['content'],
            'title' => $data['title'],
            'images'=> join(',',$data['images']),
            'avatar'=> $data['images'][0],
            'status'=>0,
            'uid'=>$data['uid'],
            'total_price'=>$price,
            'single_price'=>$singlePrice,
            'user_count'=>$package->count,
            'share_left_count'=>$package->count
        ];

        $this->dao->create($insertData);

        // #todo 支付逻辑
        //$this->paySuccess($insertData['order_sn']);
        return WechatService::create()->jsPay($user->wechat_openid,$insertData['order_sn'],bcmul(100,$insertData['total_price']),'发布广告任务','publish_ad');
    }


    // #todo 微信公众号支付回调
    public function paySuccess($orderSn)
    {
        $order = $this->dao->getWhere(['status'=>0,'order_sn'=>$orderSn]);
        if(!$order) return;

        $order->save(['status'=>1]);
    }


    // #todo 微信公众号退款
    public function refund($orderSn)
    {
        $order = $this->dao->getWhere(['status'=>1,'order_sn'=>$orderSn]);
        if(!$order) return;

        $refundOrderSn = getOrderSn('R');
        WechatService::create()->payRefund($order->order_sn,$refundOrderSn,$order->total_price,$order->total_price,'任务审核不通过退款');
        // todo 公众号退款
        $order->save(['status'=>-1,'refund_order_sn'=>$refundOrderSn]);
    }


}